﻿namespace Vibstudio.NetConfigurator.UI.ViewModels
{
    #region Namespaces

    using System;
    using System.ComponentModel;
    using System.IO;
    using System.Windows;
    using System.Windows.Forms;
    using System.Windows.Input;

    using Vibstudio.NetConfigurator.Engine;
    using Vibstudio.NetConfigurator.Globalization;
    using Vibstudio.NetConfigurator.UI.Common;
    using Vibstudio.NetConfigurator.UI.Model;

    using DirectoryNotFoundException = Vibstudio.NetConfigurator.Exceptions.DirectoryNotFoundException;
    using MessageBox = System.Windows.MessageBox;

    #endregion

    public class HomeViewModel : ViewModelBase
    {
        #region Fields

        private bool _isEnabled;
        private string _rootPath;
        private bool _isBackup;
        private bool _isConfigModeExpanded;
        private bool _isConfiguration;
        private bool _isComposition;
        private string _configuration;
        private string _composition;
        private string _configMode;
        private bool _operationInProgress;

        private RelayCommand _browseCommand;
        private RelayCommand _executeConfigurationCommand;

        #endregion

        #region Properties

        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                base.OnPropertyChanged("IsEnabled");
            }
        }

        public string RootPath
        {
            get { return _rootPath; }
            set
            {
                _rootPath = value;
                base.OnPropertyChanged("RootPath");
            }
        }

        public bool IsBackup
        {
            get { return _isBackup; }
            set
            {
                _isBackup = value;
                base.OnPropertyChanged("IsBackup");
            }
        }

        public bool IsConfigModeExpanded
        {
            get { return _isConfigModeExpanded; }
            set
            {
                _isConfigModeExpanded = value;
                base.OnPropertyChanged("IsConfigModeExpanded");
            }
        }

        public bool IsConfiguration
        {
            get { return _isConfiguration; }
            set
            {
                if (value)
                {
                    ConfigMode = Labeler.Get.ConfigurationMode.ToString();
                    base.ChooseApplicationPathToolTip = Labeler.Get.ChooseApplicationsPathToConfigure.ToString();
                    base.RunConfigurationToolTip = Labeler.Get.RunConfiguration.ToString();
                }
                _isConfiguration = value;
                if (_isConfiguration == _isComposition) IsComposition = !_isConfiguration;
                base.OnPropertyChanged("IsConfiguration");
            }
        }

        public bool IsComposition
        {
            get { return _isComposition; }
            set
            {
                if (value)
                {
                    ConfigMode = Labeler.Get.CompositionMode.ToString();
                    base.ChooseApplicationPathToolTip = Labeler.Get.ChooseApplicationsPathToCompose.ToString();
                    base.RunConfigurationToolTip = Labeler.Get.RunComposition.ToString();
                }
                _isComposition = value;
                if (_isComposition == _isConfiguration) IsConfiguration = !_isComposition;
                base.OnPropertyChanged("IsComposition");
            }
        }

        public string Configuration
        {
            get { return _configuration; }
            set
            {
                _configuration = value;
                base.OnPropertyChanged("Configuration");
            }
        }

        public string Composition
        {
            get { return _composition; }
            set
            {
                _composition = value;
                base.OnPropertyChanged("Composition");
            }
        }

        public string ConfigMode
        {
            get { return _configMode; }
            set
            {
                _configMode = value;
                base.OnPropertyChanged("ConfigMode");
            }
        }

        public bool OperationInProgress
        {
            get { return _operationInProgress; }
            set
            {
                _operationInProgress = value;
                base.OnPropertyChanged("OperationInProgress");
                
            }
        }

        #endregion

        #region Ctor(s)

        public HomeViewModel()
        {
            IsEnabled = true;
            IsBackup = true;
            IsConfigModeExpanded = false;
            IsConfiguration = true;
            IsComposition = false;
            Configuration = Labeler.Get.Configuration.ToString();
            Composition = Labeler.Get.Composition.ToString();
            OperationInProgress = false;
        }

        #endregion

        #region Commands

        public ICommand BrowseCommand
        {
            get { return _browseCommand ?? (_browseCommand = new RelayCommand(param => Browse())); }
        }

        public ICommand ExecuteConfigurationCommand
        {
            get
            {
                return _executeConfigurationCommand ?? (_executeConfigurationCommand = new RelayCommand(param => Configure(), param => IsValidRootPath()));
            }
        }

        #endregion

        #region Methods

        #region Configuration

        private void ExecuteConfiguration()
        {
            OperationInProgress = true;
            IsEnabled = false;

            var configurationWorker = new BackgroundWorker();
            configurationWorker.DoWork += ConfigurationWorkerDoWork;
            configurationWorker.RunWorkerCompleted += ConfigurationWorkerRunWorkerCompleted;
            configurationWorker.RunWorkerAsync(this);
        }

        private void ConfigurationWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            if (Directory.Exists(RootPath))
            {
                e.Result = new ResultConfigurationCollection(ConfigurationManager.Setup(RootPath, IsBackup).Configure());
            }
            else
            {
                throw new DirectoryNotFoundException();
            }
        }

        private void ConfigurationWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                ViewModelLocator.SetChild(
                    ViewRepository.Get.ResultConfiguration(
                        e.Result as ResultConfigurationCollection, _rootPath));
            }
            catch (Exception exception)
            {
                string message = exception.InnerException != null
                                     ? exception.InnerException.Message
                                     : exception.Message;
                MessageBox.Show(message, e.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                OperationInProgress = false;
                IsEnabled = true;
            }
        }

        #endregion

        #region Composition

        private void ExecuteComposition()
        {
            OperationInProgress = true;
            IsEnabled = false;

            var compositionWorker = new BackgroundWorker();
            compositionWorker.DoWork += CompositionWorkerDoWork;
            compositionWorker.RunWorkerCompleted += CompositionWorkerRunWorkerCompleted;
            compositionWorker.RunWorkerAsync(this);
        }

        private void CompositionWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            if (Directory.Exists(RootPath))
            {
                e.Result = new ResultConfigurationCollection(CompositionManager.Setup(RootPath, IsBackup).Compose());
            }
            else
            {
                throw new DirectoryNotFoundException();
            }
        }

        private void CompositionWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                ViewModelLocator.SetChild(
                    ViewRepository.Get.ResultComposition(
                        e.Result as ResultConfigurationCollection));
            }
            catch (Exception exception)
            {
                string message = exception.InnerException != null
                                     ? exception.InnerException.Message
                                     : exception.Message;
                MessageBox.Show(message, e.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                OperationInProgress = false;
                IsEnabled = true;
            }
        }

        #endregion

        #region Support

        private void Browse()
        {
            var dialog = new FolderBrowserDialog
                             {
                                 Description = base.ChooseApplicationPathToolTip
                             };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                RootPath = dialog.SelectedPath;
            }
        }

        private void Configure()
        {
            if (_isConfiguration) ExecuteConfiguration();
            if (_isComposition) ExecuteComposition();
        }

        private bool IsValidRootPath()
        {
            return Directory.Exists(_rootPath);
        }

        #endregion

        #endregion
    }
}